﻿using System;
using System.Net;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using ToyChat.Client;

namespace ToyChat.BuiltinModules
{
    /// <summary>
    /// This serves as the "Connect To" dialog
    /// </summary>
    public partial class ConnectionSetup : UserControl, IDialog
    {
        private IConnectionSettings settings = new ConnectionSettings();

        /// <summary>
        /// Fired when the user presses the OK button and the settings of this instance have been "validated" (<see cref="T0yK4T.Tools.IValidatable.Validate()"/>)
        /// </summary>
        public event RoutedEventHandler OK;

        /// <summary>
        /// Fired when the user cancels the input
        /// </summary>
        public event RoutedEventHandler Cancel;


        private bool passChanged = false;
        private bool otherChanged = false;
        private bool loading = false;

        /// <summary>
        /// Initializes a new empty instance of <see cref="ConnectionSetup"/>
        /// </summary>
        public ConnectionSetup()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Gets or Sets the settings that are displayed in this instance of <see cref="ConnectionSetup"/>
        /// </summary>
        public IConnectionSettings Settings
        {
            get { return this.settings; }
            set
            {
                this.loading = true;
                this.settings = value;
                this.hostBox1.Text = this.settings.RemoteAddress.ToString();
                this.portBox1.Text = this.settings.RemotePort.ToString();
                this.usernameBox1.Text = this.settings.Username;
                this.passwordBox1.Password = string.IsNullOrEmpty(settings.Password) ? string.Empty : "Not your password ;)";
                this.nickBox1.Text = this.settings.Nickname;
                this.registerBox1.IsChecked = this.settings.Register;
                this.emailBox1.Text = this.settings.Email;
                this.emailBox1.Visibility = ((bool)this.registerBox1.IsChecked) ? System.Windows.Visibility.Visible : System.Windows.Visibility.Hidden;
                this.emailBlock1.Visibility = ((bool)this.registerBox1.IsChecked) ? System.Windows.Visibility.Visible : System.Windows.Visibility.Hidden;
                this.loading = false;
            }
        }

        /// <summary>
        /// Gets the main input field of this dialog
        /// </summary>
        public IInputElement MainInput
        {
            get { return this.hostBox1; }
        }

        private void cancelButton1_Click(object sender, RoutedEventArgs e)
        {
            this.OnCancel();
        }

        private void okButton1_Click(object sender, RoutedEventArgs e)
        {
            ushort port;
            if (!ushort.TryParse(this.portBox1.Text, out port))
            {
                MessageBox.Show("Port is invalid", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            if (otherChanged)
            {
                this.settings.RemoteAddress = this.hostBox1.Text;
                this.settings.RemotePort = port;
                this.settings.Email = this.emailBox1.Text;
                this.settings.Nickname = this.nickBox1.Text;
                this.settings.Register = (bool)this.registerBox1.IsChecked;
                this.settings.Username = this.usernameBox1.Text;
            }
            if (passChanged)
                this.settings.Password = this.passwordBox1.Password;

            if (!settings.Validate())
            {
                MessageBox.Show("Unable to validate settings", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            this.OnOK();
        }

        private void OnOK()
        {
            if (this.OK != null)
                this.OK.Invoke(this, new RoutedEventArgs());
        }

        private void OnCancel()
        {
            if (this.Cancel != null)
                this.Cancel.Invoke(this, new RoutedEventArgs());
        }

        private IPAddress GetAddress(string hostname)
        {
            try
            {
                IPAddress[] addresses = Dns.GetHostAddresses(hostname);
                if (addresses != null)
                {
                    IPAddress actual = null;
                    foreach (IPAddress addr in addresses)
                    {
                        if (addr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                        {
                            actual = addr;
                            break;
                        }
                    }
                    return actual;
                }
                return null;
            }
            catch { return null; }
        }

        private void registerBox1_Click(object sender, RoutedEventArgs e)
        {
            this.emailBlock1.Visibility = ((bool)this.registerBox1.IsChecked) ? System.Windows.Visibility.Visible : System.Windows.Visibility.Hidden;
            this.emailBox1.Visibility = ((bool)this.registerBox1.IsChecked) ? System.Windows.Visibility.Visible : System.Windows.Visibility.Hidden;
        }

        private void hostBox1_TextChanged(object sender, TextChangedEventArgs e)
        {
            this.otherChanged = !this.loading;
        }

        private void passwordBox1_PasswordChanged(object sender, RoutedEventArgs e)
        {
            this.passChanged = !this.loading;
        }

        private void box_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
        {
            TextBox tb;
            PasswordBox pw;
            if ((tb = sender as TextBox) != null)
                tb.SelectAll();
            else if ((pw = sender as PasswordBox) != null)
                pw.SelectAll();
        }
    }
}
